# Each team member would need to set their directory path to variable "project_dir"
# we will make sure everything else is relative to "project_dir"
project_dir <- "/home/admin-12/Documents/IMARTICUS/Data-Riders/EDA"
setwd(project_dir)

# Setup Packages
load_packages <- function () {
  # Imports
  packages <- c("VIM", "dplyr", "plotly", "psych", "corrplot", "cluster", "factoextra", "psych")
  installed_packages <- packages %in% rownames(installed.packages())
  if (any(installed_packages == FALSE)) {
    install.packages(packages[!installed_packages])
  }
  # Packages loading with suppressed messages
  suppressMessages(invisible(lapply(packages, library, character.only = TRUE)))
}
load_packages()

# Get the Raw Data from the file
read_file <- function () {
  data <- read.csv("data/cereals_data.csv")
  return (data)
}

# Handle missing values
handle_missing_values <- function (input) {
  output <- input
  output <- kNN(output)
  return (output)
}

# Clearn the data to make it good for processing
# eg. delete unwanted rows, change data types etc
data_processing <- function (input) {
  output <- input
  output <- handle_missing_values(output)

  # Set company names
  output$mfr_names <- as.character(output$mfr)
  output$mfr_names[output$mfr_names=="A"] <- "American Home Food Products"
  output$mfr_names[output$mfr_names=="G"] <- "General Mills"
  output$mfr_names[output$mfr_names=="K"] <- "Kelloggs"
  output$mfr_names[output$mfr_names=="N"] <- "Nabisco"
  output$mfr_names[output$mfr_names=="P"] <- "Post"
  output$mfr_names[output$mfr_names=="Q"] <- "Quaker Oats"
  output$mfr_names[output$mfr_names=="R"] <- "Ralston Purina"
  output$mfr_names_factor = as.factor(output$mfr_names)

  # Calorie Categories
  output <- within(output, {
    calories_category <- NA
    calories_category[calories>=50&calories<80] <- "L"
    calories_category[calories>=80&calories<110] <- "M"
    calories_category[calories>=110] <- "H"
  })

  # some data processing steps that would be required
  return (output)
}

# Get the Data Frame for the data
get_data <- function () {
  raw <- read_file()
  data <- data_processing(raw)
  return (data)
}

data <- get_data()
data_grp_mfr <- data %>% group_by(mfr_names_factor)

Part #: Understanding Variables

Overall View
draw_density_plot <- function (value_set, xlab) {
  skewness <- round(skew(value_set), 2)
  mean <- round(mean(value_set), 2)
  median <- round(median(value_set), 2)
  title <- paste(xlab, "Density Chart   |  ", "Skewness:", skewness)
  plot(density(value_set), ylab = "Probabilty Density", xlab = xlab, main=title,)
  abline(v=mean, col="red")
  abline(v=median, col="blue")
}
Distribution of Calories (in the Products)
draw_density_plot(data$calories, "Calories")

Distribution of Ratings (for the Products)
draw_density_plot(data$rating, "Rating")

Relationship of one variable with another
cor_result <- cor((data_grp_mfr %>% select_if(is.numeric))[-1])
corrplot(cor_result)

heatmap(cor_result)

good_bad_corr <- function (cor_result_filter) {
  #cor_result_filter <-
  cor_result_filter_names <- names(cor_result_filter)
  names(cor_result_filter) <- NULL
  cor_result_df <- data.frame(cor_result_filter_names, cor_result_filter) %>% arrange(cor_result_filter)
  names(cor_result_df) <- c("Parameters", "Corellation")
  ggplot(cor_result_df, aes(x=Parameters, y=Corellation)) + geom_bar(stat = "identity") +
          theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"))
}
Influencers for Ratings
good_bad_corr(cor_result["rating",])

Influencers for Calories
good_bad_corr(cor_result["calories",])

Whats you get in one Serving
data %>% ggplot(aes(x = cups, fill = mfr_names)) +
        geom_histogram() +
        scale_x_continuous(name = "# of Cups", expand = c(0,0)) +
        labs(fill = "Manufacturer", title = "Distribution of cups per Serving",
             subtitle = "different cups for servings", y="# of Products") +
        theme_classic() + scale_fill_brewer(palette="Dark2")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

data %>% ggplot(aes(x = weight, fill = mfr_names)) + geom_histogram() +
    scale_x_continuous(name = "Weight (in ounces)", expand = c(0,0)) +
    labs(fill = "Manufacturer", title = "Distribution of Weight per Serving", subtitle = "Weight per serving") +
    theme_classic() + scale_fill_brewer(palette="Dark2")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Best in the Market
d <- data %>% arrange(rating) %>% head(4) %>% select(name, rating)
ggplot(data=d, aes(x=name, y=rating)) + geom_bar(stat = "identity") +
        labs(y="Ratings") + scale_fill_brewer(palette="Dark2") +
        theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"))

Part #:

Company wise Rating Consistency

data_grp_mfr %>% plot_ly(y= ~rating, x= ~mfr_names_factor, type = "box", color= ~mfr_names_factor) %>%
  layout(title="Product Consistency", xaxis=list(title="Manufactures"), yaxis=list(title="Rating"))

Company wise Calorie Consistency

data_grp_mfr %>% plot_ly(y= ~calories, x= ~mfr_names_factor, type = "box", color= ~mfr_names_factor) %>%
  layout(title="Product Consistency (by Calories)", xaxis=list(title="Manufactures"), yaxis=list(title="Calories"))

Part #:

Distribution of Rating vs Calorie Category

data %>% ggplot(aes(x = rating, fill = calories_category)) + geom_histogram() + scale_fill_brewer(palette = "Set1") +
        scale_x_continuous(name = "Ratings", expand = c(0,0)) +
        labs(fill = " Cal ", y ='Count', title = "Distribution of Rating vs Calorie Category", subtitle = "Low rating for High calories") +
        theme_classic()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Word Cloud (error in markdown)

#get_file_content <- function () {
#  txt <- readLines("data/health.txt")
#  txt <- paste(txt, collapse = " ")
#  txt <- tolower(txt)
#  txt <- gsub("[^a-zA-Z]", " ", txt)
#  txt <- gsub("\\s+", " ", txt)
#  txt <- removeWords(txt, stopwords())
#  words <- strsplit(txt, " ")
#  word_freq <- table(words)
#  return (word_freq)
#}
#word_freq <- get_file_content()
#wordcloud2(word_freq, size=10)

Cluster Analysis

cluster_data <- data %>% select(calories, rating, protein, fat) %>% scale
row.names(cluster_data) <- data[,1]
km.res <- kmeans(cluster_data, 5, nstart = 25)
fviz_cluster(km.res, data=cluster_data, palette = "jco", ggtheme = theme_minimal())

LS0tCnRpdGxlOiAiRGF0YSBSaWRlcnMgTm90ZWJvb2siCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCmg1IHsKICAgIGJhY2tncm91bmQ6IHJnYmEoMTA4LCAxMDgsIDEwOCwgMC4zNSk7CiAgICBib3JkZXItdG9wOiAxcHggc29saWQgIzg0ODQ4NDsKICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjODQ4NDg0OwogICAgbWFyZ2luLXRvcDogMHB4OwogICAgcGFkZGluZzogMTBweCAxMHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KaDU6aG92ZXIgewogIGJhY2tncm91bmQ6ICNmZmViM2I7Cn0KCmgyIHsKICBiYWNrZ3JvdW5kOiAjMjEyMTIxOwogIGNvbG9yOiB3aGl0ZTsKICBwYWRkaW5nOiA4cHggOHB4OwogIG1hcmdpbi10b3A6IDBweDsKICBtYXJnaW4tYm90dG9tOiAwcHg7Cn0KCi5jb250YWluZXItcGFydCB7CiAgYm9yZGVyOiAxcHggc29saWQgI2EyYTJhMjsKICBtYXJnaW4tYm90dG9tOiAzNXB4Owp9CgoubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTMwMHB4OwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIG1hcmdpbi1yaWdodDogYXV0bzsKfQo8L3N0eWxlPgoKYGBge3J9CiMgRWFjaCB0ZWFtIG1lbWJlciB3b3VsZCBuZWVkIHRvIHNldCB0aGVpciBkaXJlY3RvcnkgcGF0aCB0byB2YXJpYWJsZSAicHJvamVjdF9kaXIiCiMgd2Ugd2lsbCBtYWtlIHN1cmUgZXZlcnl0aGluZyBlbHNlIGlzIHJlbGF0aXZlIHRvICJwcm9qZWN0X2RpciIKcHJvamVjdF9kaXIgPC0gIi9ob21lL2FkbWluLTEyL0RvY3VtZW50cy9JTUFSVElDVVMvRGF0YS1SaWRlcnMvRURBIgpzZXR3ZChwcm9qZWN0X2RpcikKCiMgU2V0dXAgUGFja2FnZXMKbG9hZF9wYWNrYWdlcyA8LSBmdW5jdGlvbiAoKSB7CiAgIyBJbXBvcnRzCiAgcGFja2FnZXMgPC0gYygiVklNIiwgImRwbHlyIiwgInBsb3RseSIsICJwc3ljaCIsICJjb3JycGxvdCIsICJjbHVzdGVyIiwgImZhY3RvZXh0cmEiLCAicHN5Y2giKQogIGluc3RhbGxlZF9wYWNrYWdlcyA8LSBwYWNrYWdlcyAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKQogIGlmIChhbnkoaW5zdGFsbGVkX3BhY2thZ2VzID09IEZBTFNFKSkgewogICAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlc1shaW5zdGFsbGVkX3BhY2thZ2VzXSkKICB9CiAgIyBQYWNrYWdlcyBsb2FkaW5nIHdpdGggc3VwcHJlc3NlZCBtZXNzYWdlcwogIHN1cHByZXNzTWVzc2FnZXMoaW52aXNpYmxlKGxhcHBseShwYWNrYWdlcywgbGlicmFyeSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkpCn0KbG9hZF9wYWNrYWdlcygpCgojIEdldCB0aGUgUmF3IERhdGEgZnJvbSB0aGUgZmlsZQpyZWFkX2ZpbGUgPC0gZnVuY3Rpb24gKCkgewogIGRhdGEgPC0gcmVhZC5jc3YoImRhdGEvY2VyZWFsc19kYXRhLmNzdiIpCiAgcmV0dXJuIChkYXRhKQp9CgojIEhhbmRsZSBtaXNzaW5nIHZhbHVlcwpoYW5kbGVfbWlzc2luZ192YWx1ZXMgPC0gZnVuY3Rpb24gKGlucHV0KSB7CiAgb3V0cHV0IDwtIGlucHV0CiAgb3V0cHV0IDwtIGtOTihvdXRwdXQpCiAgcmV0dXJuIChvdXRwdXQpCn0KCiMgQ2xlYXJuIHRoZSBkYXRhIHRvIG1ha2UgaXQgZ29vZCBmb3IgcHJvY2Vzc2luZwojIGVnLiBkZWxldGUgdW53YW50ZWQgcm93cywgY2hhbmdlIGRhdGEgdHlwZXMgZXRjCmRhdGFfcHJvY2Vzc2luZyA8LSBmdW5jdGlvbiAoaW5wdXQpIHsKICBvdXRwdXQgPC0gaW5wdXQKICBvdXRwdXQgPC0gaGFuZGxlX21pc3NpbmdfdmFsdWVzKG91dHB1dCkKCiAgIyBTZXQgY29tcGFueSBuYW1lcwogIG91dHB1dCRtZnJfbmFtZXMgPC0gYXMuY2hhcmFjdGVyKG91dHB1dCRtZnIpCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iQSJdIDwtICJBbWVyaWNhbiBIb21lIEZvb2QgUHJvZHVjdHMiCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iRyJdIDwtICJHZW5lcmFsIE1pbGxzIgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IksiXSA8LSAiS2VsbG9nZ3MiCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iTiJdIDwtICJOYWJpc2NvIgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IlAiXSA8LSAiUG9zdCIKICBvdXRwdXQkbWZyX25hbWVzW291dHB1dCRtZnJfbmFtZXM9PSJRIl0gPC0gIlF1YWtlciBPYXRzIgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IlIiXSA8LSAiUmFsc3RvbiBQdXJpbmEiCiAgb3V0cHV0JG1mcl9uYW1lc19mYWN0b3IgPSBhcy5mYWN0b3Iob3V0cHV0JG1mcl9uYW1lcykKCiAgIyBDYWxvcmllIENhdGVnb3JpZXMKICBvdXRwdXQgPC0gd2l0aGluKG91dHB1dCwgewogICAgY2Fsb3JpZXNfY2F0ZWdvcnkgPC0gTkEKICAgIGNhbG9yaWVzX2NhdGVnb3J5W2NhbG9yaWVzPj01MCZjYWxvcmllczw4MF0gPC0gIkwiCiAgICBjYWxvcmllc19jYXRlZ29yeVtjYWxvcmllcz49ODAmY2Fsb3JpZXM8MTEwXSA8LSAiTSIKICAgIGNhbG9yaWVzX2NhdGVnb3J5W2NhbG9yaWVzPj0xMTBdIDwtICJIIgogIH0pCgogICMgc29tZSBkYXRhIHByb2Nlc3Npbmcgc3RlcHMgdGhhdCB3b3VsZCBiZSByZXF1aXJlZAogIHJldHVybiAob3V0cHV0KQp9CgojIEdldCB0aGUgRGF0YSBGcmFtZSBmb3IgdGhlIGRhdGEKZ2V0X2RhdGEgPC0gZnVuY3Rpb24gKCkgewogIHJhdyA8LSByZWFkX2ZpbGUoKQogIGRhdGEgPC0gZGF0YV9wcm9jZXNzaW5nKHJhdykKICByZXR1cm4gKGRhdGEpCn0KCmRhdGEgPC0gZ2V0X2RhdGEoKQpkYXRhX2dycF9tZnIgPC0gZGF0YSAlPiUgZ3JvdXBfYnkobWZyX25hbWVzX2ZhY3RvcikKYGBgCgo8IS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0+CjxkaXYgY2xhc3M9ImNvbnRhaW5lci1wYXJ0Ij4KPGgyPlBhcnQgIzogVW5kZXJzdGFuZGluZyBWYXJpYWJsZXM8L2gxPgoKPGg1Pk92ZXJhbGwgVmlldzwvaDU+CgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkZXNjcmliZShkYXRhICU+JSBzZWxlY3RfaWYoaXMubnVtZXJpYykpCmBgYAoKYGBge3J9CmRyYXdfZGVuc2l0eV9wbG90IDwtIGZ1bmN0aW9uICh2YWx1ZV9zZXQsIHhsYWIpIHsKICBza2V3bmVzcyA8LSByb3VuZChza2V3KHZhbHVlX3NldCksIDIpCiAgbWVhbiA8LSByb3VuZChtZWFuKHZhbHVlX3NldCksIDIpCiAgbWVkaWFuIDwtIHJvdW5kKG1lZGlhbih2YWx1ZV9zZXQpLCAyKQogIHRpdGxlIDwtIHBhc3RlKHhsYWIsICJEZW5zaXR5IENoYXJ0ICAgfCAgIiwgIlNrZXduZXNzOiIsIHNrZXduZXNzKQogIHBsb3QoZGVuc2l0eSh2YWx1ZV9zZXQpLCB5bGFiID0gIlByb2JhYmlsdHkgRGVuc2l0eSIsIHhsYWIgPSB4bGFiLCBtYWluPXRpdGxlLCkKICBhYmxpbmUodj1tZWFuLCBjb2w9InJlZCIpCiAgYWJsaW5lKHY9bWVkaWFuLCBjb2w9ImJsdWUiKQp9CmBgYAoKPGg1PkRpc3RyaWJ1dGlvbiBvZiBDYWxvcmllcyAoaW4gdGhlIFByb2R1Y3RzKTwvaDU+CmBgYHtyfQpkcmF3X2RlbnNpdHlfcGxvdChkYXRhJGNhbG9yaWVzLCAiQ2Fsb3JpZXMiKQpgYGAKCjxoNT5EaXN0cmlidXRpb24gb2YgUmF0aW5ncyAoZm9yIHRoZSBQcm9kdWN0cyk8L2g1PgpgYGB7cn0KZHJhd19kZW5zaXR5X3Bsb3QoZGF0YSRyYXRpbmcsICJSYXRpbmciKQpgYGAKCjxoNT5SZWxhdGlvbnNoaXAgb2Ygb25lIHZhcmlhYmxlIHdpdGggYW5vdGhlcjwvaDU+CmBgYHtyfQpjb3JfcmVzdWx0IDwtIGNvcigoZGF0YV9ncnBfbWZyICU+JSBzZWxlY3RfaWYoaXMubnVtZXJpYykpWy0xXSkKY29ycnBsb3QoY29yX3Jlc3VsdCkKaGVhdG1hcChjb3JfcmVzdWx0KQpgYGAKCmBgYHtyfQpnb29kX2JhZF9jb3JyIDwtIGZ1bmN0aW9uIChjb3JfcmVzdWx0X2ZpbHRlcikgewogICNjb3JfcmVzdWx0X2ZpbHRlciA8LQogIGNvcl9yZXN1bHRfZmlsdGVyX25hbWVzIDwtIG5hbWVzKGNvcl9yZXN1bHRfZmlsdGVyKQogIG5hbWVzKGNvcl9yZXN1bHRfZmlsdGVyKSA8LSBOVUxMCiAgY29yX3Jlc3VsdF9kZiA8LSBkYXRhLmZyYW1lKGNvcl9yZXN1bHRfZmlsdGVyX25hbWVzLCBjb3JfcmVzdWx0X2ZpbHRlcikgJT4lIGFycmFuZ2UoY29yX3Jlc3VsdF9maWx0ZXIpCiAgbmFtZXMoY29yX3Jlc3VsdF9kZikgPC0gYygiUGFyYW1ldGVycyIsICJDb3JlbGxhdGlvbiIpCiAgZ2dwbG90KGNvcl9yZXN1bHRfZGYsIGFlcyh4PVBhcmFtZXRlcnMsIHk9Q29yZWxsYXRpb24pKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpKQp9CmBgYAoKPGg1PkluZmx1ZW5jZXJzIGZvciBSYXRpbmdzPC9oNT4KYGBge3J9Cmdvb2RfYmFkX2NvcnIoY29yX3Jlc3VsdFsicmF0aW5nIixdKQpgYGAKCjxoNT5JbmZsdWVuY2VycyBmb3IgQ2Fsb3JpZXM8L2g1PgpgYGB7cn0KZ29vZF9iYWRfY29ycihjb3JfcmVzdWx0WyJjYWxvcmllcyIsXSkKYGBgCgo8aDU+V2hhdHMgeW91IGdldCBpbiBvbmUgU2VydmluZzwvaDU+CmBgYHtyfQpkYXRhICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXBzLCBmaWxsID0gbWZyX25hbWVzKSkgKwogICAgICAgIGdlb21faGlzdG9ncmFtKCkgKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIiMgb2YgQ3VwcyIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgICAgIGxhYnMoZmlsbCA9ICJNYW51ZmFjdHVyZXIiLCB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgY3VwcyBwZXIgU2VydmluZyIsCiAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJkaWZmZXJlbnQgY3VwcyBmb3Igc2VydmluZ3MiLCB5PSIjIG9mIFByb2R1Y3RzIikgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikKYGBgCgpgYGB7cn0KZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0LCBmaWxsID0gbWZyX25hbWVzKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIldlaWdodCAoaW4gb3VuY2VzKSIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgbGFicyhmaWxsID0gIk1hbnVmYWN0dXJlciIsIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBXZWlnaHQgcGVyIFNlcnZpbmciLCBzdWJ0aXRsZSA9ICJXZWlnaHQgcGVyIHNlcnZpbmciKSArCiAgICB0aGVtZV9jbGFzc2ljKCkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpCmBgYAoKPGg1PkJlc3QgaW4gdGhlIE1hcmtldDwvaDU+CmBgYHtyfQpkIDwtIGRhdGEgJT4lIGFycmFuZ2UocmF0aW5nKSAlPiUgaGVhZCg0KSAlPiUgc2VsZWN0KG5hbWUsIHJhdGluZykKZ2dwbG90KGRhdGE9ZCwgYWVzKHg9bmFtZSwgeT1yYXRpbmcpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICAgbGFicyh5PSJSYXRpbmdzIikgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpKQpgYGAKCjwvZGl2PgoKPCEtLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tPgo8ZGl2IGNsYXNzPSJjb250YWluZXItcGFydCI+CjxoMj5QYXJ0ICM6IDwvaDE+CkNvbXBhbnkgd2lzZSBSYXRpbmcgQ29uc2lzdGVuY3kKCmBgYHtyIG91dC53aWR0aD0iMTAwJSJ9CmRhdGFfZ3JwX21mciAlPiUgcGxvdF9seSh5PSB+cmF0aW5nLCB4PSB+bWZyX25hbWVzX2ZhY3RvciwgdHlwZSA9ICJib3giLCBjb2xvcj0gfm1mcl9uYW1lc19mYWN0b3IpICU+JQogIGxheW91dCh0aXRsZT0iUHJvZHVjdCBDb25zaXN0ZW5jeSIsIHhheGlzPWxpc3QodGl0bGU9Ik1hbnVmYWN0dXJlcyIpLCB5YXhpcz1saXN0KHRpdGxlPSJSYXRpbmciKSkKYGBgCgpDb21wYW55IHdpc2UgQ2Fsb3JpZSBDb25zaXN0ZW5jeQpgYGB7ciBvdXQud2lkdGg9IjEwMCUifQpkYXRhX2dycF9tZnIgJT4lIHBsb3RfbHkoeT0gfmNhbG9yaWVzLCB4PSB+bWZyX25hbWVzX2ZhY3RvciwgdHlwZSA9ICJib3giLCBjb2xvcj0gfm1mcl9uYW1lc19mYWN0b3IpICU+JQogIGxheW91dCh0aXRsZT0iUHJvZHVjdCBDb25zaXN0ZW5jeSAoYnkgQ2Fsb3JpZXMpIiwgeGF4aXM9bGlzdCh0aXRsZT0iTWFudWZhY3R1cmVzIiksIHlheGlzPWxpc3QodGl0bGU9IkNhbG9yaWVzIikpCmBgYAo8L2Rpdj4KCjxkaXYgY2xhc3M9ImNvbnRhaW5lci1wYXJ0Ij4KPGgyPlBhcnQgIzogPC9oMT4KCkRpc3RyaWJ1dGlvbiBvZiBSYXRpbmcgdnMgQ2Fsb3JpZSBDYXRlZ29yeQpgYGB7cn0KZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0gcmF0aW5nLCBmaWxsID0gY2Fsb3JpZXNfY2F0ZWdvcnkpKSArIGdlb21faGlzdG9ncmFtKCkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArCiAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiUmF0aW5ncyIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgICAgIGxhYnMoZmlsbCA9ICIgQ2FsICIsIHkgPSdDb3VudCcsIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBSYXRpbmcgdnMgQ2Fsb3JpZSBDYXRlZ29yeSIsIHN1YnRpdGxlID0gIkxvdyByYXRpbmcgZm9yIEhpZ2ggY2Fsb3JpZXMiKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpCmBgYAoKV29yZCBDbG91ZCAoZXJyb3IgaW4gbWFya2Rvd24pCmBgYHtyfQojZ2V0X2ZpbGVfY29udGVudCA8LSBmdW5jdGlvbiAoKSB7CiMgIHR4dCA8LSByZWFkTGluZXMoImRhdGEvaGVhbHRoLnR4dCIpCiMgIHR4dCA8LSBwYXN0ZSh0eHQsIGNvbGxhcHNlID0gIiAiKQojICB0eHQgPC0gdG9sb3dlcih0eHQpCiMgIHR4dCA8LSBnc3ViKCJbXmEtekEtWl0iLCAiICIsIHR4dCkKIyAgdHh0IDwtIGdzdWIoIlxccysiLCAiICIsIHR4dCkKIyAgdHh0IDwtIHJlbW92ZVdvcmRzKHR4dCwgc3RvcHdvcmRzKCkpCiMgIHdvcmRzIDwtIHN0cnNwbGl0KHR4dCwgIiAiKQojICB3b3JkX2ZyZXEgPC0gdGFibGUod29yZHMpCiMgIHJldHVybiAod29yZF9mcmVxKQojfQojd29yZF9mcmVxIDwtIGdldF9maWxlX2NvbnRlbnQoKQojd29yZGNsb3VkMih3b3JkX2ZyZXEsIHNpemU9MTApCmBgYAoKQ2x1c3RlciBBbmFseXNpcwpgYGB7cn0KY2x1c3Rlcl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChjYWxvcmllcywgcmF0aW5nLCBwcm90ZWluLCBmYXQpICU+JSBzY2FsZQpyb3cubmFtZXMoY2x1c3Rlcl9kYXRhKSA8LSBkYXRhWywxXQprbS5yZXMgPC0ga21lYW5zKGNsdXN0ZXJfZGF0YSwgNSwgbnN0YXJ0ID0gMjUpCmZ2aXpfY2x1c3RlcihrbS5yZXMsIGRhdGE9Y2x1c3Rlcl9kYXRhLCBwYWxldHRlID0gImpjbyIsIGdndGhlbWUgPSB0aGVtZV9taW5pbWFsKCkpCmBgYAoKCg==